package com.fdl.service.security.impl;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;

import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.providers.dao.SaltSource;
import org.acegisecurity.providers.encoding.PasswordEncoder;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.fdl.common.exception.security.DeleteUserSelfException;
import com.fdl.common.exception.security.LoginTimeOutException;
import com.fdl.dao.model.security.Permission;
import com.fdl.dao.model.security.Role;
import com.fdl.dao.model.security.User;
import com.fdl.dao.security.UserDao;
import com.fdl.service.security.SecurityService;

/**
 * 
 * @description 
 * @project: hb-intra
 * @Date:2010-8-4
 * @version  1.0
 * @Company: 33e9
 * @author zhangYong.huang
 */
public class SecurityServiceImpl implements SecurityService {
	private static final String NO_PERMISSION = "无权管理此用户";

	protected Log log = LogFactory.getLog(this.getClass());

	private PasswordEncoder passwordEncoder;

	private SaltSource saltSource;
	
	private UserDao userDao;

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public PasswordEncoder getPasswordEncoder() {
		return passwordEncoder;
	}

	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	public SaltSource getSaltSource() {
		return saltSource;
	}

	public void setSaltSource(SaltSource saltSource) {
		this.saltSource = saltSource;
	}

	/**
	 * 假删除,把状态设置为-1
	 * 用户自己不能删除自己
	 * @throws DeleteUserSelfException
	 * @throws LoginTimeOutException 
	 */
	public void deleteUsers(Serializable[] ids) throws DeleteUserSelfException, LoginTimeOutException {
		for (int i = 0; i < ids.length; i++) {
			User user = User.loadById(ids[i]);

			if (user != null) {
				checkSuperUser(user);
				user.delete();
			}
		}
	}

	/**
	 * 用户状态设为停用
	 */
	public void disableUsers(Serializable[] ids) {
		for (int i = 0; i < ids.length; i++) {
			User user = User.loadById(ids[i]);

			if (user != null) {
				checkSuperUser(user);
				user.disable();
			}
		}
	}

	/**
	 * 用户状态设为可用
	 */
	public void enableUsers(Serializable[] ids) {
		for (int i = 0; i < ids.length; i++) {
			User user = User.loadById(ids[i]);

			if (user != null) {
				checkSuperUser(user);
				user.enable();
			}
		}
	}

	/**
	 * 登陆成功
	 */
	public void onSuccessLogin(User user, String loginAddress) {
		try{
			userDao.onSuccessLogin(user.getId(), loginAddress);			
		}catch(Exception e){
			log.error("onSuccessLogin failed!", e);
		}
	}

	/**
	 * 获取所有用户
	 * 非系统管理员不用看到系统管理员帐户
	 */
	public List getAllUsers() {
		List list = User.getAll();
		if (!SecurityUtils.isSuperUser()) {
			Iterator it = list.iterator();
			while (it.hasNext()) {
				User user = (User) it.next();
				if (user.hasPermission(Permission.PERMISSION_NAME_SUPER_USER))
					it.remove();
			}
		}
		return list;
	}

	/**
	 * 判断是否是系统管理员，
	 * 不是则抛出AccessDeniedException
	 * @param user
	 */
	protected void checkSuperUser(User user) {
		if (!SecurityUtils.isSuperUser()) {
			if (user.hasPermission(Permission.PERMISSION_NAME_SUPER_USER))
				throw new AccessDeniedException(NO_PERMISSION);
		}
	}

	/**
	 * 获取所有角色
	 * 非系统管理员不用看到系统管理员角色
	 */
	public List getAllRoles() {
		List list = Role.getAll();
		if (!SecurityUtils.isSuperUser()) {
			Iterator it = list.iterator();
			while (it.hasNext()) {
				Role role = (Role) it.next();
				if (role.hasPermission(Permission.PERMISSION_NAME_SUPER_USER))
					it.remove();
			}
		}
		return list;
	}

	/**
	 * 重设密码
	 * 只有系统管理员才有权限
	 */
	public void resetPassword(Serializable id, String newPass) {
		User user = User.loadById(id);
		checkSuperUser(user);
		user.setPassword(passwordEncoder.encodePassword(newPass, saltSource
				.getSalt(user)));

	}

	/**
	 * 修改密码
	 * 输入错误老密码会抛出BadCredentialsException
	 * @throws LoginTimeOutException 
	 */
	public void modifyPassword(String oldPass, String newPass) throws BadCredentialsException, LoginTimeOutException{
		User user = SecurityUtils.getCurrentUser();

		if (!passwordEncoder.isPasswordValid(user.getPassword(), oldPass,
				saltSource.getSalt(user))) {
			throw new BadCredentialsException("Wrong old password");
		}

		user.setPassword(passwordEncoder.encodePassword(newPass, saltSource
				.getSalt(user)));
		user.save();
	}

	protected void copyBeanProperties(Object dest, Object src) {
		try {
			PropertyUtils.copyProperties(dest, src);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public List getAvailableUsersByRole(Role role) {
		return User.getAvailableUsersByRole(role);
	}

	public List getAllPermissions() {
		return Permission.getAll();
	}

}
